/***************************************************************
*  Copyright (c) 2007 by GroupMe! Team (www.groupme.net)
*  All rights reserved.
*
*  This file is part of the GroupMe! Project. Source code of 
*  this project is closed and redistribution of this code is
*  prohibited. 
*  
*  Contact: http://www.groupme.net
*
*  This copyright notice MUST APPEAR in all copies of the file!
***************************************************************/
package net.groupme.mail;

import java.io.UnsupportedEncodingException;
import java.util.Properties;

import javax.mail.PasswordAuthentication;
import javax.mail.Session;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;

import net.groupme.exceptions.MailException;
import net.groupme.model.User;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.mail.javamail.JavaMailSenderImpl;
import org.springframework.mail.javamail.MimeMessageHelper;

/**
 * created on Jul 27, 2007
 * 
 * This class provides functionality for sending emails to a GroupMe! user.
 * 
 * @author Fabian Abel, <a href="mailto:abel@l3s.de">abel@l3s.de</a>
 * @author last edited by: $Author: fabian $
 * 
 * @version $Revision: 1.2 $ $Date: 2007-07-31 13:54:56 $
 */
public class MailSenderUtility {

	
	/** Logger for this class */
	private static final Log logger = LogFactory.getLog(MailSenderUtility.class);
	
	private static String SMTP_USERNAME = MailSenderPropertyManager.getString("mail.smtp.username"); //$NON-NLS-1$
	private static String SMTP_PASSWORD = MailSenderPropertyManager.getString("mail.smtp.password"); //$NON-NLS-1$
	private static String SMTP_HOST = MailSenderPropertyManager.getString("mail.smtp.host"); //$NON-NLS-1$
	private static final int SMTP_PORT = 465;
	
	/** The Mail-Sender instance */
	private static JavaMailSenderImpl sender = new JavaMailSenderImpl();
	//Achtung: Die Reihenfolge (Order/Export) von activation.jar und mail.jar spielt eine Rolle. 
	//         Wenn man eine "javax.mail.NoSuchProviderException: smtp.." bekommt, sollte man sich
	//         Order/Export mal anschauen.
	static {
		Properties props = new Properties();
		props.put("mail.smtp.auth", "true"); //$NON-NLS-1$ //$NON-NLS-2$
		props.put("mail.smtp.socketFactory.class", //$NON-NLS-1$
				"javax.net.ssl.SSLSocketFactory"); //$NON-NLS-1$
		props.put("mail.smtp.socketFactory.fallback", "false"); //$NON-NLS-1$ //$NON-NLS-2$
		//props.put("mail.debug", "true");//$NON-NLS-1$ //$NON-NLS-2$
		sender.setJavaMailProperties(props);
		sender.setHost(SMTP_HOST);
		sender.setUsername(SMTP_USERNAME);
		sender.setPassword(SMTP_PASSWORD);
		sender.setPort(SMTP_PORT);
		Session session = Session.getInstance(props,
				new javax.mail.Authenticator() {

					protected PasswordAuthentication getPasswordAuthentication() {
						return new PasswordAuthentication(SMTP_USERNAME, SMTP_PASSWORD);
					}
				});
		sender.setSession(session);
	}
	/** mail address of the GroupMe! Team */
	private static final String GROUPME_MAIL_ADRESS = MailSenderPropertyManager.getString("mail.sender.address"); //$NON-NLS-1$
	
	/** mail sender name */
	private static final String GROUPME_MAIL_SENDER = MailSenderPropertyManager.getString("mail.sender.name"); //$NON-NLS-1$

	/** indicates system notifications */
	private static final String GROUPME_NOTIFICATION_INDICATOR = MailSenderPropertyManager.getString("mail.indicator"); //$NON-NLS-1$ 
	
	/** malinglist receivers */
	private static final String[] GROUPME_NOTIFICATION_RECEIVERS = MailSenderPropertyManager.getStringArray("mail.list.receiver"); //$NON-NLS-1$ 
	
	/** Sender Mail Adress */
	private static InternetAddress from = new InternetAddress();
	static {
		from.setAddress(GROUPME_MAIL_ADRESS);
		try {
			from.setPersonal(GROUPME_MAIL_SENDER);
		} catch (UnsupportedEncodingException e) {
			e.printStackTrace();
			logger.error("Unallowed Mail Sender Name: " + GROUPME_MAIL_SENDER); //$NON-NLS-1$
		}
	}

	/**
	 * This method sends an email to the new registered user 
	 * containing his account details (also the password).
	 * @param user the new user
	 * @param password the user's password
	 * @return <code>true</code> if mail was successfully sent otherwise <code>false</code>
	 * @throws MailException thrown if it fails to send the mail
	 */
	public static void sendWelcomeMail(User user, String password) throws MailException{
		String messageText = "Howdy " + user.getFirstName() + "!<br/>" + //$NON-NLS-1$ //$NON-NLS-2$
			"<p>Welcome to GroupMe! Your account was successfully created:</p>" + //$NON-NLS-1$
				"<blockquote>username: " + user.getUserName() + "<br/>" + //$NON-NLS-1$ //$NON-NLS-2$
				"password: " + password + "</blockquote>" + //$NON-NLS-1$ //$NON-NLS-2$
			"<p>Visit <a href=\"http://groupme.org/\">http://groupme.org</a> to start using GroupMe! and keep yourself informed by subscribing to the GroupMe! blog: <a href=\"http://groupme.org/blog/\">http://groupme.org/blog/</a></p>" + //$NON-NLS-1$
			"<p>If you have any questions or suggestions feel free to contact us: <a href=\"mailto:" + GROUPME_MAIL_ADRESS + "/\">" + GROUPME_MAIL_ADRESS + " </a></p>" + //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
			"<p>Have fun!<br/><br/><i>Your GroupMe! Team</i></p>"; //$NON-NLS-1$
		
		sendMail(user.getFirstName() + " " + user.getLastName(), user.getEmail(), "GroupMe! account", messageText); //$NON-NLS-1$ //$NON-NLS-2$
		
		//Notify the Team...
		messageText = "Dear all, <br/><p>a new user has registered to GroupMe! Account details:</p>" +
				"<blockquote>username: " + user.getUserName() + "<br/>" +
				"first name: " + user.getFirstName() + "<br/>" +
				"last name: " + user.getLastName() + "<br/>" +
				"email: " + user.getEmail() + "<br/>" +
				"foaf: " + user.getFoaf() +
				"</blockquote>" +
				"<p>Cheers,<br/><br/><i>Your GroupMe! System</i></p>";
		sendMail(GROUPME_NOTIFICATION_RECEIVERS, GROUPME_NOTIFICATION_INDICATOR + " New User", messageText); //$NON-NLS-1$ //$NON-NLS-2$
	}
	
	/**
	 * Utility function to send a mail from {@link MailSenderUtility#GROUPME_MAIL_ADRESS} to the given 
	 * mail address.
	 * @param toName the name of the receiver
	 * @param toAddress the email address of the receiver
	 * @param subject the subject of the mail
	 * @param messageText the HTML-formatted message text
	 * @throws MailException thrown if an error occurs when sending the mail.
	 */
	private static void sendMail(String toName, String toAddress, String subject, String messageText) throws MailException{
		logger.info("Sending an email to: " + toName + "<" + toAddress + "> with suject: " + subject);
		MimeMessage message = sender.createMimeMessage();

		//use the true flag to indicate you need a multipart message
		MimeMessageHelper helper;
		try {
			helper = new MimeMessageHelper(message, false);
			InternetAddress to = new InternetAddress();
			to.setAddress(toAddress);
			try {
				to.setPersonal(toName);
			} catch (UnsupportedEncodingException e) {
				logger.error("Unallowed Mail Receiver Name: " + toName + ". Message will be send without a name but just with the To-Mail-Address."); //$NON-NLS-1$ //$NON-NLS-2$
			}
			helper.setTo(to);
			helper.setFrom(from);
			helper.setSubject(subject);

			//use the flag to indicate the text included is HTML
			helper.setText(messageText, true);
			sender.send(message);
		} catch (Exception e) {
			throw new MailException("Problems on sending mail...", e); //$NON-NLS-1$
		} 
	}
	
	/**
	 * Utility function to send a mail from {@link MailSenderUtility#GROUPME_MAIL_ADRESS} to a list of given 
	 * mail addresses.
	 * @param toAddresses the email addresses of the receivers
	 * @param subject the subject of the mail
	 * @param messageText the HTML-formatted message text
	 * @throws MailException thrown if an error occurs when sending the mail.
	 */
	private static void sendMail(String[] toAddresses, String subject, String messageText) throws MailException{
		logger.info("Sending an email to a mailinglist. Suject: " + subject);
		MimeMessage message = sender.createMimeMessage();

		//use the true flag to indicate you need a multipart message
		MimeMessageHelper helper;
		try {
			helper = new MimeMessageHelper(message, false);
			helper.setTo(toAddresses);
			helper.setFrom(from);
			helper.setSubject(subject);

			//use the flag to indicate the text included is HTML
			helper.setText(messageText, true);
			sender.send(message);
		} catch (Exception e) {
			throw new MailException("Problems on sending mail...", e); //$NON-NLS-1$
		} 
	}
}
